package com.flowCloud.config.token;


import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.flowCloud.config.exception.BadRequestParameterException;
import com.flowCloud.web.bean.TblUserBean;
import io.jsonwebtoken.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * tokenTool
 * @author leopard
 *
 */
public class JwtTokenUtil {
    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_NAME= "token";
    public static final String TOKEN_PREFIX = "Bearer ";

    private static final String SECRET = "jwtsecretinmobi";
    private static final String ISS = "leopard";

    // 过期时间是64800秒，既是18个小时
    public static final long EXPIRATION = 64800L;

    // 选择了记住我之后的过期时间为30天
    public static final long EXPIRATION_REMEMBER = 86400 * 30;

    /**
     * 创建token
     * 注：如果是根据可变的唯一值来生成，唯一值变化时，需重新生成token
     *
     * @param isRememberMe
     * @return
     */
    public static String createToken(String id, TblUserBean t, boolean isRememberMe) {
        long expiration = isRememberMe ? EXPIRATION_REMEMBER : EXPIRATION;
        //可以将基本不重要的对象信息放到claims中，此处信息不多,见简单直接放到配置内
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                // 这里要早set一点，放到后面会覆盖别的字段
                .setIssuer(ISS)
                .setId(id)
                .setSubject(JSONUtil.toJsonStr(t))
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                .compact();
    }

    /**
    * @Description: 获取用户信息
    * @Author: Pompey_hpy
    * @Date: 2021-01-08
    * @param request
    * @return: java.lang.Object
    */
    public static TblUserBean getUserInfo(HttpServletRequest request) {
        // 取得token
        String token = request.getHeader(JwtTokenUtil.TOKEN_NAME);
        String subject = getTokenBody(token).getSubject();

        return JSONUtil.toBean(getTokenBody(token).getSubject(),TblUserBean.class);
    }


    /**
     * 从token中获取ID
     *
     * @param token
     * @return
     */
    public static String getObjectId(String token) {
        return getTokenBody(token).getId();
    }

    /**
     * 是否已过期
     *
     * @param token
     * @return
     * @throws过期无法判断，只能通过捕获ExpiredJwtException异常
     */
    @Deprecated
    public static boolean isExpiration(String token) {
        return getTokenBody(token).getExpiration().before(new Date());
    }

    /**
     * 获取token信息，同时也做校验处理
     *
     * @param token
     * @return
     * @throws自定义UserLoginException异常处理
     */
    public static Claims getTokenBody(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException expired) {
            //过期
            throw new BadRequestParameterException("10210", "token失效,请重新登录！");
        } catch (SignatureException e) {
            //无效
            throw new BadRequestParameterException("5001", "无效token");
        } catch (MalformedJwtException malformedJwt) {
            //无效
            throw new BadRequestParameterException("5001", "无效token");
        }
    }

}
